{% extends "announce.html" %}

{% block head %}
{{ super() }}
<script type='text/javascript'>
// <![CDATA[
//

//
// Functions used to display the build status bubble on box click.
//

// show the build status box. This is called when the user clicks on a block.
function showBuildBox(url, event) {
    //  Find the current curson position.
    var cursorPosTop = (window.event ? window.event.clientY : event.pageY)
    var cursorPosLeft = (window.event ? window.event.clientX : event.pageX)

    // Offset the position by 5, to make the window appears under the cursor.
    cursorPosTop  = cursorPosTop  + document.body.scrollTop -5 ;    
    cursorPosLeft = cursorPosLeft  + document.body.scrollLeft - 5;

    // Move the div (hidden) under the cursor.
    var divBox = document.getElementById('divBox');
    divBox.style.top = parseInt(cursorPosTop) + 'px';
    divBox.style.left = parseInt(cursorPosLeft) + 'px';

    // Reload the hidden frame with the build page we want to show.
    // The onload even on this frame will update the div and make it visible.
    document.getElementById("frameBox").src = url
    
    // We don't want to reload the page.
    return false;
}

// OnLoad handler for the iframe containing the build to show.
function updateDiv(event) { 
    // Get the frame innerHTML.
    var iframeContent = document.getElementById("frameBox").contentWindow.document.body.innerHTML;

    // If there is any content, update the div, and make it visible.
    if (iframeContent) {
        var divBox = document.getElementById('divBox'); 
        divBox.innerHTML = iframeContent ;
        divBox.style.display = "block";
    }
} 

// Util functions to know if an element is contained inside another element.
// We use this to know when we mouse out our build status div.
function containsDOM (container, containee) {
    var isParent = false;
    do {
        if ((isParent = container == containee))
            break;
        containee = containee.parentNode;
    } while (containee != null);

    return isParent;
}

// OnMouseOut handler. Returns true if the mouse moved out of the element.
// It is false if the mouse is still in the element, but in a blank part of it,
// like in an empty table cell.
function checkMouseLeave(element, event) {
  if (element.contains && event.toElement) {
    return !element.contains(event.toElement);
  }
  else if (event.relatedTarget) {
    return !containsDOM(element, event.relatedTarget);
  }
}

// Returns the value of a GET parameter, or null if it does not exist.
function readGetParameter(name) {
  var begin = name + '=';
  var data = location.search;
  if (data === '') {
    return null;
  }
  // Location starts with "?".
  data = data.substr(1);
  var parameters = data.split("&");
  for (var index = 0; index < parameters.length; index++) {
    var parameter = parameters[index];
    if (parameter.indexOf(begin) == 0)
      return decodeURIComponent(
          parameter.substring(begin.length));
  }
  return null;
}

// Creates a new cookie.
function createCookie(name, value, day) {
    var date = new Date();
    date.setTime(date.getTime() + (day * 24 * 60 * 60 * 1000));
    var expires = "; expires=" + date.toGMTString();
    document.cookie = name + "=" + value+expires + "; path=/";
}

// Returns the value of a cookie, or null if it does not exist.
function readCookie(name) {
    var begin = name + "=";
    var data = document.cookie.split(';');
    for(var i = 0; i < data.length; i++) {
        var cookie = data[i];
        while (cookie.charAt(0) == ' ')
            cookie = cookie.substring(1, cookie.length);
        if (cookie.indexOf(begin) == 0)
            return cookie.substring(begin.length, cookie.length);
    }

    return null;
}

// Deletes a cookie.
function eraseCookie(name) {
    createCookie(name, "", -1);
}

// Hides all "details" and "comments" section.
function collapse() {
    // Hide all Comments sections.
    var comments = document.querySelectorAll('.DevComment');
    for(var i = 0; i < comments.length; i++) {
        comments[i].style.display = "none";
    }

    // Hide all details sections.
    var details = document.querySelectorAll('.DevDetails');
    for(var i = 0; i < details.length; i++) {
        details[i].style.display = "none";
    }

    // Fix the rounding on the Revision box. (Lower right corner must be round)
    var revisions = document.querySelectorAll('.DevRev');
    for(var i = 0; i < revisions.length; i++) {
      revisions[i].className = revisions[i].className + ' DevRevCollapse';
    }

    // Fix the rounding on the last category box. (Lower left corner must be round)
    var status = document.querySelectorAll('.last');
    for(var i = 0; i < status.length; i++) {
        status[i].className = status[i].className + ' DevStatusCollapse';
    }

    // Create a cookie to remember that we want the view to be collapsed.
    createCookie('collapsed', 'true', 30)

    // Hide the collapse and the unmerge buttons.
    document.querySelectorAll('.collapse')[0].style.display = 'none'
    document.querySelectorAll('.unmerge')[0].style.display = 'none'

    // Activate the merge and expand buttons.
    document.querySelectorAll('.uncollapse')[0].style.display = 'inline'
    document.querySelectorAll('.merge')[0].style.display = 'inline'
}

// Expands the view. This is the opposite of "Collapse"
function uncollapse() {
    unmerge();

    // Make the comments visible.
    var comments = document.querySelectorAll('.DevComment');
    for(var i = 0; i < comments.length; i++) {
        comments[i].style.display = "";
    }

    // Make the details visible.
    var details = document.querySelectorAll('.DevDetails');
    for(var i = 0; i < details.length; i++) {
        details[i].style.display = "";
    }

    // Remove the round corner (lower right) for the Revision box.
    var revisions = document.querySelectorAll('.DevRev');
    for(var i = 0; i < revisions.length; i++) {
        revisions[i].className = revisions[i].className.replace('DevRevCollapse', '');
    }

    // Remoe the round corner (lower left) for the last category box.
    var status = document.querySelectorAll('.DevStatus');
    for(var i = 0; i < status.length; i++) {
        status[i].className = status[i].className.replace('DevStatusCollapse', '');
    }

    // Delete the cookies that say that we want to be collapsed or merged.
    eraseCookie('collapsed')
    eraseCookie('merged')

    // Display the "collapse" and "merge" buttons.
    document.querySelectorAll('.collapse')[0].style.display = 'inline'
    document.querySelectorAll('.merge')[0].style.display = 'inline'

    // Remove the "uncollapse" and "unmerge" buttons.
    document.querySelectorAll('.uncollapse')[0].style.display = 'none'
    document.querySelectorAll('.unmerge')[0].style.display = 'none'
}

// Merge all the status boxes together.
function merge() {
    collapse();

    // Hide all the spacing.
    var spacing = document.querySelectorAll('.DevStatusSpacing');
    for(var i = 0; i < spacing.length; i++) {
        spacing[i].style.display = "none";
    }

    // Each boxes have, in the className, a tag that uniquely represents the
    // build where this data comes from.
    // Since we  want to merge all the boxes coming from the same build, we
    // parse the document to find all the builds, and then, for each build, we
    // concatenate the boxes.

    var allTags = [];
    all = document.getElementsByTagName('*')
    for(var i = 0; i < all.length; i++) {
        var element = all[i];
        start = element.className.indexOf('Tag')
        if (start != -1) {
            var className = ""
            end = element.className.indexOf(' ', start)
            if (end != -1) {
                className = element.className.substring(start, end);
            } else {
                className = element.className.substring(start);
            }
            allTags[className] = 1;
        }
    }

    // Mergeall tags that we found
    for (i in allTags) {
        var current = document.querySelectorAll('.' + i);

        // We do the work only if there is more than 1 box with the same
        // build.
        if (current.length > 1) {
            // Add the noround class to all the boxes.
            for(var i = 0; i < current.length; i++) {
                current[i].className = current[i].className + ' noround';
            }

            // Add the begin class to the first box.
            current[0].className = current[0].className + ' begin';

            // Add the end class to the last box.
            last = current.length - 1;
            current[last].className = current[last].className + ' end';
        }
    }

    // Display the "unmerge" button.
    document.querySelectorAll('.unmerge')[0].style.display = 'inline'
    document.querySelectorAll('.uncollapse')[0].style.display = 'inline'

    // Remove the "merge" button.
    document.querySelectorAll('.collapse')[0].style.display = 'none'
    document.querySelectorAll('.merge')[0].style.display = 'none'

    // Create a cookie to remember that we want to be merged.
    createCookie('merged', 'true', 30)
}

// Un-merge the view. This is the opposite of "merge".
function unmerge() {
    // We put back all the spacing.
    var spacing = document.querySelectorAll('.DevStatusSpacing');
    for(var i = 0; i < spacing.length; i++) {
        spacing[i].style.display = "";
    }

    // We remove the class added to all the boxes we modified.
    var noround = document.querySelectorAll('.noround');
    for(var i = 0; i < noround.length; i++) {
        noround[i].className = noround[i].className.replace("begin", '');
        noround[i].className = noround[i].className.replace("end", '');
        noround[i].className = noround[i].className.replace("noround", '');
    }

    // Delete the cookie, we don't want to be merged anymore.
    eraseCookie('merged')

    // Display the "merge" button.
    document.querySelectorAll('.merge')[0].style.display = 'inline'

    // Hide the "unmerge" button.
    document.querySelectorAll('.unmerge')[0].style.display = 'none'
}

function SetupView() {
    // Allow override cookies with Get parameters.
    var getMerged = readGetParameter('merged');
    if (getMerged === 'true') {
        createCookie('merged', 'true', 30);
    }
    if (getMerged === 'false') {
        eraseCookie('merged');
    }
    var getCollapsed = readGetParameter('collapsed');
    if (getCollapsed === 'true') {
        createCookie('collapsed', 'true', 30);
    }
    if (getCollapsed === 'false') {
        eraseCookie('collapsed');
    }

    if (readCookie('merged')) {
        merge();
    } else if (readCookie('collapsed')) {
        collapse();
    }
}

document.addEventListener("DOMContentLoaded", SetupView, false);

// ]]> 
</script>
{% endblock %}

{% block content %}

<div align="center">
  <table width="95%" class="Grid" border="0" cellspacing="0">
    <tr>
      <td width="33%" align="left" class="left_align">
{% if repository %}
        <br><b>Repository:</b> {{ repository|e }}
{% endif %}
{% if branch != ANYBRANCH %}
        <br><b>Branch:</b> {{ branch|e }}
{% endif %}
      </td>
      <td width="33%" align="center" class="center_align">
        <div align="center">
          <table class="info">
            <tr>
              <td>Legend:&nbsp;&nbsp;</td>
              <td class='legend success' title='All tests passed'>Passed</td>
              <td class='legend failure' title='There is a new failure. Take a look!'>Failed</td>
              <td class='legend warnings' title='It was failing before, and it is still failing. Make sure you did not introduce new regressions'>Failed&nbsp;Again</td>
              <td class='legend running' title='The tests are still running'>Running</td>
              <td class='legend exception' title='Something went wrong with the test, there is no result'>Exception</td>
              <td class='legend offline' title='The builder is offline, as there are no slaves connected to it'>Offline</td>
              <td class='legend notstarted' title='No result yet.'>No&nbsp;data</td>
            </tr>
          </table>
        </div>
      </td>
      <td width="33%" align="right" class="right_align">
      <script type="text/javascript"> 
// <![CDATA[
          function reload_page() {
            name_value = document.getElementById('namebox').value
            if (document.location.href.lastIndexOf('?') == -1)
              document.location.href = document.location.href+ '?name=' + name_value;
            else
              document.location.href = document.location.href+ '&name=' + name_value;
          }
// ]]> 
        </script>
        <input id='namebox' name='name' type='text' style='color:#999;'
            onblur='this.value = this.value || this.defaultValue; this.style.color = "#999";'
            onfocus='this.value=""; this.style.color = "#000";'
            value='Personalized for...'/>      
        <input type='submit' value='Go' onclick='reload_page()'/>
      </td>
     </tr>
  </table>
</div>

<br/>

{% set alt_class = cycler('', 'Alt') %}

<div align="center">
<table width="96%">
  
{% if categories|length > 1 %}
  <tr>
    <td width="1%">
    </td>
    <td width="1%">
    </td>
  {% for c in categories %}
      <td class='DevStatus Alt {{ "first" if loop.first else '' }} {{ "last" if loop.last else '' }}' width='{{ c.size }}%'>
        {{ c.name|numstrip }}
      </td>
  {% endfor %}
  </tr>
  <tr class='DevStatusSpacing'>
  </tr>
{% endif %}

{% if slaves %}
  <tr>
    <td width="1%">
    </td>
    <td width="1%">
    </td>
  {% for c in categories %}
    <td class='DevSlave Alt {{ "last" if loop.last else '' }}'>
      <table width="100%">
        <tr>          
    {% for s in slaves[c.name] %}          
          <td class='DevSlaveBox'>
            <a href='{{ s.url }}' title='{{ s.pageTitle }}' class='DevSlaveBox {{ s.color }}' target="_blank">
            </a>
          </td>
    {% endfor %}            
        </tr>
      </table>
    </td>
  {% endfor %}
  </tr>
{% endif %}
  
{% for r in revisions %}
  {% set alt = alt_class.next() %}
  {% set last = "last" if loop.last else "" %}

  <tr>
    <td class='DevRev {{ alt }} DevRevCollapse' width="1%">
      <a href="{{ r.link }}" target="_blank">{{ r.id|shortrev(r.repository) }}</a>
    </td>
    <td class='DevName {{ alt }}' width="1%">
      {{ r.who|user }}
    </td>

  {% for c in categories %}
    <td class='DevStatus {{ alt }} {% if loop.last %}DevStatusCollapse{% endif %}'>
      <table width="100%">
        <tr>    
    {% for b in r.builds[c.name] %}
          <td class='DevStatusBox'>
            <a href='#' onclick='showBuildBox("{{ b.url }}", event); return false;'
               title='{{ b.pageTitle|e }}' class='DevStatusBox {{ b.color }} {{ b.tag }}'
               target="_blank"></a>
          </td>
    {% endfor %}    
        </tr>
      </table>
    </td>
  {% endfor %}
  </tr>
   
  <tr>
    <td colspan="{{ r.span }}" class='DevComment {{ alt }}'> 
      {{ r.comments|changecomment(r.project or None)|replace('\n', '<br/>')|replace('  ','&nbsp; ') }}
    </td>
  </tr>
 
  {% if r.details %}
  <tr>
    <td colspan="{{ r.span }}" class='DevDetails {{ alt }}'>
      <ul style='margin: 0px; padding: 0 0 0 1.5em;'>
    {% for d in r.details %}
        <li>{{ d.buildername }}: {{ d.status }} - &nbsp;
      {%- for l in d.logs -%}
            <a href="{{ l.url }}"> {{ l.name }} </a>{% if not loop.last	%} - {%	endif %}
      {%- endfor -%}
        </li>
    {% endfor %}
      </ul>
    </td>
  </tr>    
  {% endif %} 

  <tr class='DevStatusSpacing'>
    <td>
    </td>
  </tr>  
{% else %}
 <tr><td>No revisions available</td></tr>
{% endfor %}
  
</table>
</div>


<div id="divBox" onmouseout="if (checkMouseLeave(this, event)) this.style.display = 'None'" class="BuildWaterfall"> 
</div>


<iframe id="frameBox" style="display: none;"></iframe>
  
<script type="text/javascript">
// replace 'onload="updateDiv(event);" with this, as iframe doesn't have onload event in xhtml
window.onload = function() {
  document.getElementById('frameBox').onload = function(event) {
    updateDiv(event);
  };
}; 
</script>

{% endblock %}


{% block footer %}
<div class="footer" style="clear:both">
  <hr/>
  [ <a class='collapse' href='#' OnClick='collapse(); return false;'>collapse</a>
  <a class='uncollapse' href='#' OnClick='uncollapse(); return false;'>un-collapse</a>
  <a class='merge' href="#" OnClick="merge(); return false;">merge</a>
  <a class='unmerge' style='display: none' href="#" OnClick="unmerge(); return false;">un-merge</a> ]
</div>
{% endblock %}
